﻿using System;
using System.Collections.Generic;
 
using System.Text;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.IO;
 
namespace DataProvider
{
    public class DBGernerator
    {
        private static String[] reservedField = new string[] { "ID", "flagForBak", "CreateDate" };
        public String NameSpace = "Entity";
        private String connString = "Server={0};Database={1};User ID={2};password={3}";
        private String outPutFolder = "";
        private String[] specifiedTables = null;
        public DBGernerator(String server, String dbname, String user, String pwd, String outPutFolder, params String[] specifiedTables)
        {
            connString = String.Format(connString, server, dbname, user, pwd);
            this.outPutFolder = outPutFolder;
            if (!Directory.Exists(this.outPutFolder))
            {
                Directory.CreateDirectory(this.outPutFolder);
            }
            this.specifiedTables = specifiedTables;
        }

        private List<TableInfo> GetTableInfo()
        {
            String sql = "select id,name from sysobjects where (type = 'U' Or type = 'V') and name <>'dtproperties' ";
            SqlClient sqlClient = new SqlClient(this.connString);
            List<TableInfo> tableInfoList = new List<TableInfo>();
            using (DbDataReader reader = sqlClient.ExecuteReader(sql))
            {
                while (reader.Read())
                {
                    String tableName =  reader.GetString(1);
                    if (this.specifiedTables != null && this.specifiedTables.Length > 0)
                    {
                        if (StringUtils.ContainStringInList(this.specifiedTables,tableName, true))
                        {
                            TableInfo tableInfo = new TableInfo();
                            tableInfo.TableId = reader.GetInt32(0);
                            tableInfo.TableName = tableName;
                            tableInfoList.Add(tableInfo);
                        }
                    }
                    else
                    {
                        TableInfo tableInfo = new TableInfo();
                        tableInfo.TableId = reader.GetInt32(0);
                        tableInfo.TableName = tableName;
                        tableInfoList.Add(tableInfo);
                    }
                   
                }
            }
            return tableInfoList;
        }

        private List<TableFieldInfo> GetFieldInfo(String tableName)
        {
            String sql = @" select  A.name as fieldname ,B.name as  type 
                            from  syscolumns A inner join systypes B ON A.xtype=B.xtype and B.name<>'sysname'
                            where  A.id=object_id('{0}') ";
            sql = String.Format(sql, tableName);
            SqlClient sqlClient = new SqlClient(this.connString);
            List<TableFieldInfo> fieldList = new List<TableFieldInfo>();
            using (DbDataReader reader = sqlClient.ExecuteReader(sql))
            {
                while (reader.Read())
                {
                    String fieldName = reader.GetString(0);
                    if (StringUtils.ContainStringInList(reservedField, fieldName, true))  
                    {
                        continue;
                    }
                    TableFieldInfo fieldInfo = new TableFieldInfo();
                    fieldInfo.FieldName = fieldName;
                    fieldInfo.FieldType = reader.GetString(1);
                    fieldList.Add(fieldInfo);
                }
            }
            return fieldList;
        }

        public void GenerateCode()
        {
            List<TableInfo> tableList = GetTableInfo();
            SqlConfigFile configfile = new SqlConfigFile();
            String configFileName = outPutFolder +"/" +"EntitySql.xml";
            if (File.Exists(configFileName))
            {
                configfile.LoadFile(configFileName);
            }
            //////////////////////////////////////////////////////////////////////
            foreach (TableInfo table in tableList)
            {
                List<TableFieldInfo> fieldList = GetFieldInfo(table.TableName);

                StringBuilder codeBuilder = new StringBuilder();
                foreach (TableFieldInfo fieldInfo in fieldList)
                {
                    object defaultValue;
                    codeBuilder.AppendFormat("\t\t[DBField(\"{0}\")]", fieldInfo.FieldName.ToUpper()).AppendLine();
                    codeBuilder.AppendFormat("\t\tpublic {0} {1} ={2};", GetFieldType(fieldInfo.FieldType, out defaultValue), fieldInfo.FieldName.ToUpper(), defaultValue);
                    codeBuilder.AppendLine();
                    codeBuilder.AppendLine();
                }
                String className = table.TableName.Substring(0, 1).ToUpper() + table.TableName.Substring(1);
                String template = RsUtils.GetResourceString("DataProvider.dll", "DataProvider.DBToEntity.EntityClassTp.txt");
                template = template.Replace("{_ClassName_}",className );
                template = template.Replace("{_NameSpace_}", this.NameSpace);
                template = template.Replace("{FieldInfo}", codeBuilder.ToString());

                String fileName = this.outPutFolder + "\\" + className + ".cs";
                using(StreamWriter writer = new StreamWriter(fileName,false,Encoding.Default))
                {
                    writer.Write(template);
                }
                EntitySqlConfig configItem = null;
                if (configfile.EntitySqlConfigCollection.ContainsKey(this.NameSpace + "." + className))
                {
                    configItem = configfile.EntitySqlConfigCollection[this.NameSpace + "." + className];
                }
                else
                {
                    configItem = new EntitySqlConfig();
                }
                configItem.EntityName = this.NameSpace + "." + className;
                configfile.EntitySqlConfigCollection[this.NameSpace + "." + className] = configItem;

                Console.WriteLine("{0} 生成...", className);
            }
            configfile.SaveFile(configFileName);

            Console.WriteLine("生成完成.");
        }

        private String GetFieldType(String fieldDbType,out object defaultValue)
        {
            if (String.Compare("decimal", fieldDbType, true) == 0)
            {
                defaultValue = "0.0M";
                return "decimal";
            }
            if (String.Compare("nchar", fieldDbType, true) == 0||
                String.Compare("nvarchar", fieldDbType, true) == 0||
                String.Compare("char", fieldDbType, true) == 0||
                String.Compare("varchar", fieldDbType, true) == 0||
                String.Compare("text", fieldDbType, true) == 0||
                String.Compare("ntext", fieldDbType, true) == 0)
            {
                defaultValue = "\"\"";
                return "String";
            }
            if (String.Compare("int", fieldDbType, true) == 0||
                String.Compare("smallint", fieldDbType, true) == 0||
                String.Compare("bigint", fieldDbType, true) == 0)
            {
                defaultValue = "0";
                return "int";
            }
            if (String.Compare("image", fieldDbType, true) == 0||
                String.Compare("blob", fieldDbType, true) == 0)
            {
                defaultValue = "null";
                return "byte[]";
            }
            if (String.Compare("float", fieldDbType, true) == 0 )
            {
                defaultValue = "0.0F";
                return "float";
            }
            defaultValue = "\"\"";
            return "String";
        }
    }

    
}
